package com.zxtech.zzm.core.util

/**
 * reference apache commons [http://commons.apache.org/codec/](http://commons.apache.org/codec/)
 *
 * @author Aub
 */
object HexUtil {
  /**
   * 用于建立十六进制字符的输出的小写字符数组
   */
  private val DIGITS_LOWER = charArrayOf(
      '0', '1', '2', '3', '4', '5',
      '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
  )

  /**
   * 用于建立十六进制字符的输出的大写字符数组
   */
  private val DIGITS_UPPER = charArrayOf(
      '0', '1', '2', '3', '4', '5',
      '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
  )
  /**
   * 将字节数组转换为十六进制字符数组
   *
   * @param data byte[]
   * @param toLowerCase `true` 传换成小写格式 ， `false` 传换成大写格式
   * @return 十六进制char[]
   */
  /**
   * 将字节数组转换为十六进制字符数组
   *
   * @param data byte[]
   * @return 十六进制char[]
   */
  @JvmOverloads fun encodeHex(
    data: ByteArray,
    toLowerCase: Boolean = true
  ): CharArray {
    return encodeHex(data, if (toLowerCase) DIGITS_LOWER else DIGITS_UPPER)
  }

  /**
   * 将字节数组转换为十六进制字符数组
   *
   * @param data byte[]
   * @param toDigits 用于控制输出的char[]
   * @return 十六进制char[]
   */
  internal fun encodeHex(
    data: ByteArray,
    toDigits: CharArray
  ): CharArray {
    val l = data.size
    val out = CharArray(l shl 1)
    // two characters form the hex value.
    var i = 0
    var j = 0
    while (i < l) {
      out[j++] = toDigits[0xF0 and data[i]
          .toInt() ushr 4]
      out[j++] = toDigits[0x0F and data[i]
          .toInt()]
      i++
    }
    return out
  }
  /**
   * 将字节数组转换为十六进制字符串
   *
   * @param data byte[]
   * @param toLowerCase `true` 传换成小写格式 ， `false` 传换成大写格式
   * @return 十六进制String
   */
  /**
   * 将字节数组转换为十六进制字符串
   *
   * @param data byte[]
   * @return 十六进制String
   */
  @JvmOverloads fun encodeHexStr(
    data: ByteArray,
    toLowerCase: Boolean = true
  ): String {
    return encodeHexStr(data, if (toLowerCase) DIGITS_LOWER else DIGITS_UPPER)
  }

  /**
   * 将字节数组转换为十六进制字符串
   *
   * @param data byte[]
   * @param toDigits 用于控制输出的char[]
   * @return 十六进制String
   */
  internal fun encodeHexStr(
    data: ByteArray,
    toDigits: CharArray
  ): String {
    return String(encodeHex(data, toDigits))
  }

  /**
   * 将十六进制字符数组转换为字节数组
   *
   * @param data 十六进制char[]
   * @return byte[]
   * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度，将抛出运行时异常
   */
  fun decodeHex(data: CharArray): ByteArray {
    val len = data.size
    if (len and 0x01 != 0) {
      throw RuntimeException("Odd number of characters.")
    }
    val out = ByteArray(len shr 1)
    // two characters form the hex value.
    var i = 0
    var j = 0
    while (j < len) {
      var f = toDigit(data[j], j) shl 4
      j++
      f = f or toDigit(data[j], j)
      j++
      out[i] = (f and 0xFF).toByte()
      i++
    }
    return out
  }

  /**
   * 将十六进制字符转换成一个整数
   *
   * @param ch 十六进制char
   * @param index 十六进制字符在字符数组中的位置
   * @return 一个整数
   * @throws RuntimeException 当ch不是一个合法的十六进制字符时，抛出运行时异常
   */
  internal fun toDigit(
    ch: Char,
    index: Int
  ): Int {
    val digit = Character.digit(ch, 16)
    if (digit == -1) {
      throw RuntimeException(
          "Illegal hexadecimal character " + ch
              + " at index " + index
      )
    }
    return digit
  }

  /**
   * 二进制字符串转byte
   */
  fun decodeBinaryString(byteStr: String?): Byte {
    val re: Int
    val len: Int
    if (null == byteStr) {
      return 0
    }
    len = byteStr.length
    if (len != 4 && len != 8) {
      return 0
    }
    re = if (len == 8) { // 8 bit处理
      if (byteStr[0] == '0') { // 正数
        byteStr.toInt(2)
      } else { // 负数
        byteStr.toInt(2) - 256
      }
    } else { // 4 bit处理
      byteStr.toInt(2)
    }
    return re.toByte()
  }

  /**
   * 将byte转换为一个长度为8的byte数组，数组每个值代表bit
   */
  fun getBooleanArray(b: Byte): ByteArray {
    var b = b
    val array = ByteArray(8)
    for (i in 7 downTo 0) {
      array[i] = (b.toInt() and 1).toByte()
      b = (b.toInt() shr 1).toByte()
    }
    return array
  }

  /**
   * 把byte转为字符串的bit
   */
  fun byteToBit(b: Byte): String {
    return (""
        + (b.toInt() shr 7 and 0x1).toByte() + (b.toInt() shr 6 and 0x1).toByte()
        + (b.toInt() shr 5 and 0x1).toByte() + (b.toInt() shr 4 and 0x1).toByte()
        + (b.toInt() shr 3 and 0x1).toByte() + (b.toInt() shr 2 and 0x1).toByte()
        + (b.toInt() shr 1 and 0x1).toByte() + (b.toInt() shr 0 and 0x1).toByte())
  }

  //    public static void main(String[] args) {
  //        byte b = 0x35; // 0011 0101
  //        // 输出 [0, 0, 1, 1, 0, 1, 0, 1]
  //        System.out.println(Arrays.toString(getBooleanArray(b)));
  //        // 输出 00110101
  //        System.out.println(byteToBit(b));
  //        // JDK自带的方法，会忽略前面的 0
  //        System.out.println(Integer.toBinaryString(0x35));
  //    }
  @JvmStatic fun main(args: Array<String>) {
    val srcStr = "待转换字符串"
    val encodeStr = encodeHexStr(srcStr.toByteArray())
    val decodeStr = String(decodeHex(encodeStr.toCharArray()))
    println("转换前：$srcStr")
    println("转换后：$encodeStr")
    println("还原后：$decodeStr")
  }
}